package sig.dao.relational.impl.jpa;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.transaction.annotation.Transactional;

import sig.dao.relational.IDaoBase;
import sig.exceptions.SigUnCheckedException;



import java.lang.reflect.*;


/**
 * Dao generico para persistencia de objetos
 * @author orlando
 *
 * @param <T>
 */

@Transactional
public class DaoBaseJpa<T> implements IDaoBase<T> {

	private EntityManager em;

	@PersistenceContext
	public void setEntityManager(EntityManager em) {

		this.em = em;

	}

	public EntityManager getEntityManager() {

		return this.em;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T find(int id) {
		
		try {

			Class<?> claseGenerica = obtenerClaseGenerica();
			
			T generico= (T)em.find(claseGenerica, id);
			
			return generico;
			
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}

		
		return null;
	}
	
	private Class<?> obtenerClaseGenerica() throws ClassNotFoundException {
		Class<?> clase = this.getClass();
		String superClase = clase.getGenericSuperclass().toString();

		String tipo = superClase.replaceAll("^.+?<(.+?)>", "$1");

		return Class.forName(tipo);
	}

	@Override
	public void delete(int id) {
		T generico = find(id);
		em.remove(generico);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> findAll() {
		try {
			Query query = em.createQuery("from "+obtenerClaseGenerica().getName());
			return (List<T>)query.getResultList();
		} catch (ClassNotFoundException e) {
			throw new SigUnCheckedException(e);
		}
	}

	@Override
	public Integer save(T generico) {

		try {

		   em.persist((T) generico);
			
		  
			Class<?> obj = generico.getClass();

			Method method = obj.getMethod("getId", (Class<?>[]) null);

			return (Integer) method.invoke(generico, (Object[]) null);

		} catch (SecurityException e) {

			e.printStackTrace();
		} catch (NoSuchMethodException e) {

			e.printStackTrace();

		} catch (IllegalArgumentException e) {

			e.printStackTrace();

		} catch (IllegalAccessException e) {

			e.printStackTrace();

		} catch (InvocationTargetException e) {

			e.printStackTrace();

		}

		return null;
	}

	@Override
	public void update(T generico) {

		em.merge((T) generico);

	}

}
